# -*- coding: UTF-8 -*-
# @Create   : 2021/8/18 18:52
# @Author   : yh
# @Remark   : 数据处理、转换相关方法
import logging

from mxsoftpy.exception import DataError


def list_to_trees(data, parent_column="parent_code", parent_value="", child_column="children", current_column=None,
                  current_path=None, search_key=None):
    """
    将数据转换为树结构
    :param data: 数据字典
                eg:
                    {"1": {"name": "测试视频组", "parent_code": 0},
                     "2": {"name": "测试视频组", "parent_code": 1},
                     "3": {"name": "测试视频组", "parent_code": 0},
                     "4": {"name": "测试视频组", "parent_code": 1},
                     "5": {"name": "测试视频组", "parent_code": 1},
                     "6": {"name": "测试视频组", "parent_code": 5}}
    :param parent_column: 父ID字段名
    :param parent_value: 父ID根结点值，默认为0
    :param child_column: 子列表字典名称
    :param current_column: 当前展开值字段名，若找到展开值增加["open"] = "1"
    :param current_path: 当前展开值
    :param search_key: 查询关键字
    :return: 树结构
    """

    data_tree_list = []  # 整个数据大列表
    for d_id, d_dic in data.items():
        pid = d_dic.get(parent_column)  # 取每一个字典中的父id
        d_dic['code'] = d_id
        if pid == parent_value:  # 父id=查询值，就直接加入数据大列表
            data_tree_list.append(d_dic)
        else:  # 父id不等于查询值，就加入父id队对应的那个的节点列表
            try:  # 判断异常代表有子节点，增加子节点列表=[]
                data[pid][child_column].append(d_dic)
            except KeyError:
                try:
                    data[pid][child_column] = []
                    data[pid][child_column].append(d_dic)
                except KeyError:
                    pass

        # 展开节点
        if current_path:
            if current_path == d_dic.get(current_column):
                d_dic["open"] = "1"
                while pid and pid != parent_value:
                    data[pid]["open"] = "1"
                    pid = data[pid][parent_column]

    res = list()

    def search(key, tree_data) -> None:
        """
        查询能模糊匹配关键词的功能菜单数据
        :param key: 要查询的关键词
        :param tree_data: 查询tree数据
        """
        for i in tree_data:
            if i['name'].find(key) == -1:
                if i.get('children'):
                    search(key, i['children'])
            else:
                res.append(i)

    if search_key:
        search(search_key, data_tree_list)
        return res

    return data_tree_list


def list_dict(data: dict) -> dict:
    """
    将数据格式化形成列表套字典
    """
    data_l = []
    for i in data:
        data[i]['code'] = int(i)
        data_l.append(data[i])
    return {'data': data_l}


def pwd_web2db(pwd_web: str, pwd_verify: str) -> str:
    """
    将前端加密的密码转为数据库加密
    :param pwd_web: 前端密文
    :param pwd_verify: 密文验证码
    :return: 转换后的密码
    """
    from superbsapi import web_decrypt, EncryptString

    try:
        pwd = web_decrypt(pwd_web, pwd_verify)
    except Exception:
        raise ValueError('无法解码此密码')

    flag, pwd_db = EncryptString(pwd)
    if flag:
        return pwd_db
    else:
        raise ValueError('解码的密码无法加密成数据库密文')


def pwd_db2decode(pwd_db: str) -> str:
    """
    将数据库中的密码解码为明文
    :param pwd_db: 数据库密文
    :return: 密码明文
    """
    from superbsapi import DecryptString
    pwd_flag, pwd = DecryptString(pwd_db)
    if not pwd_flag:
        logging.error('无法解码的数据库密文：%s' % pwd_db)
        raise DataError('解码数据库密码失败')
    return pwd


def is_number(number):
    """判断是否为浮点型"""
    try:
        # 因为使用float有一个例外是'NaN'
        if str == 'NaN':
            return False
        float(number)
        return True
    except ValueError:
        return False


def ip_10_to_2(ip: str) -> str:
    """
    将十进制的IPv4地址转为2进制（此函数不会进行格式校验，因此请确保你的参数符合IPv4格式）
    """
    ip_list = ip.split('.')
    res = ''
    for item in ip_list:
        res += str(bin(int(item))[2:].zfill(8))
    return res


def round_to_100_percent(err_datas: list) -> dict:
    """
    计算错误类型所占百分比
    """
    err_percent_dict = {}
    err_total = sum(err_datas)
    for index,value in enumerate(err_datas):
        err_count = value
        err_type = index + 1
        err_percent = '%2d' % (err_count/err_total*100) + '%' if err_total != 0 else '0%'
        err_percent_dict[err_type] = err_percent
    return err_percent_dict
